﻿using System;
using System.ComponentModel;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.UI.Bovespa.Movimento.Communication;

namespace Sinacor.UI.Bovespa.Movimento.Presenter
{
    /// <summary>
    /// 
    /// </summary>
    public class ControleMovimentoOrdens : BasePresenter<IBaseView>, IControleMovimento
    {
        #region Construtor

        /// <summary>
        /// Construtor
        /// </summary>
        /// <param name="view">View</param>
        public ControleMovimentoOrdens(IControleMovimentoView view)
            : base((IBaseView)view)                       
        {
            this._view = view;                        
        }

        #endregion

        #region Atributos

        private Communication.Calendario _communicationCalendario;
        private Communication.ControleMovimentoBolsa _communicationControleMovimentoBolsa;
        private Communication.ControleMovimentoOrdens _communicationControleMovimentoOrdens;
        private Model.DataAtual _dataAtualSistema;
        private DateTime? _dataMovimento;
        private DateTime? _dataMovimentoD1;
        private Model.InformacoesMovimento _informacoesMovimentoBolsa;
        private Model.InformacoesMovimento _informacoesMovimentoOrdens;
        private IControleMovimentoView _view;
        private bool _faturamentoInstalado;

        #endregion

        #region Propriedades

        /// <summary>
        /// 
        /// </summary>
        public Model.DataAtual DataAtualSistema
        {
            get { return _dataAtualSistema; }
            set { _dataAtualSistema = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public DateTime? DataMovimento
        {
            get { return _dataMovimento; }
            set { _dataMovimento = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public DateTime? DataMovimentoD1
        {
            get { return _dataMovimentoD1; }
            set { _dataMovimentoD1 = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.InformacoesMovimento InformacoesMovimentoBolsa
        {
            get { return _informacoesMovimentoBolsa; }
            set { _informacoesMovimentoBolsa = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.InformacoesMovimento InformacoesMovimentoOrdens
        {
            get { return _informacoesMovimentoOrdens; }
            set { _informacoesMovimentoOrdens = value; }
        }

        #endregion

        #region Métodos Públicos

        /// <summary>
        /// 
        /// </summary>
        public void AbrirMovimento()
        {            
            if (this._view.ConfirmarAberturaMovimentoOrdens())
            {                
                try
                {
                    this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);

                    if (_dataMovimentoD1 > _dataAtualSistema.Valor)
                    {
                        if (this._view.ConfirmarAberturaMovimentoOrdensAtencao())
                        {
                            this._communicationControleMovimentoOrdens.AbrirMovimento();
                            this._view.InformarSucessoAberturaMovimentoOrdens();
                        }
                    }
                    else
                    {
                        this._communicationControleMovimentoOrdens.AbrirMovimento();
                        this._view.InformarSucessoAberturaMovimentoOrdens();
                    }
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void ConsolidarMovimento()
        {
            if (this._view.ConfirmarConsolidacaoMovimentoOrdens())
            {
                try
                {
                    this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);
                    this._communicationControleMovimentoOrdens.ConsolidarMovimento();
                    this._view.InformarSucessoConsolidacaoMovimentoOrdens();
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void FecharMovimento()
        {
            if (this._view.ConfirmarFechamentoMovimentoOrdens())
            {
                try
                {
                    Model.Parameter.DadosFechaMovimento dadosFechaMovimento = new Model.Parameter.DadosFechaMovimento();
                    dadosFechaMovimento.DataMovimento = this.InformacoesMovimentoOrdens.DataMovimento;
                    dadosFechaMovimento.ContinuaHavendoInconsistencias = true;

                    Model.DataMovimento dataMovimento = new Sinacor.UI.Bovespa.Movimento.Model.DataMovimento();
                    dataMovimento.Valor = this.InformacoesMovimentoOrdens.DataMovimento;

                    this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);
                    if (((Model.Resultado)this._communicationControleMovimentoOrdens.VerificarAlertasFechamento(dataMovimento)).Sucesso)
                    {
                        this._communicationControleMovimentoOrdens.FecharMovimento(dadosFechaMovimento);
                        this._view.InformarSucessoFechamentoMovimentoOrdens();
                    }
                    else
                    {
                        if (this._view.ConfirmarContinuidadeProcessoFechamento())
                        {
                            this._communicationControleMovimentoOrdens.FecharMovimento(dadosFechaMovimento);
                            this._view.InformarSucessoFechamentoMovimentoOrdens();
                        }
                    }
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Inicializar()
        {
            this.CarregarInformacoes();
            this.AvaliarSolicitacaoMovimento();
        }
                
        /// <summary>
        /// 
        /// </summary>
        public void ReabrirMovimento()
        {
            if (this._view.ConfirmarReaberturaMovimentoOrdens())
            {
                try
                {
                    this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);
                    this._communicationControleMovimentoOrdens.ReabrirMovimento();
                    this._view.InformarSucessoReaberturaMovimentoOrdens();
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Sair()
        {
            if (this._view.ConfirmarSaida())
                this._view.FecharTela();
        }

        /// <summary>
        /// 
        /// </summary>
        public void SimularFechamentoMovimento()
        {
            if (this._view.ConfirmarSimulacaoFechamentoMovimentoOrdens())
            {
                try
                {
                    Model.DataMovimento dataMovimento = new Model.DataMovimento();
                    dataMovimento.Valor = this.InformacoesMovimentoOrdens.DataMovimento;                    

                    this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);
                    Model.Resultado resultado = this._communicationControleMovimentoOrdens.SimularFechamentoMovimento(dataMovimento);

                    if (resultado.Sucesso)
                        this._view.InformarSucessoSimulacaoOrdens();
                    else
                    {
                        if (resultado.ImpedeFechamento)
                            this._view.InformarErroSimulacaoImpedeFechamentoOrdens();
                        else
                            this._view.InformarErroSimulacaoNaoImpedeFechamento();
                    }
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }

        #endregion

        #region Métodos Privados

        /// <summary>
        /// 
        /// </summary>
        private void AvaliarSolicitacaoMovimento()
        {
            if (this.ValidarAcaoAbrir())
                this._view.PrepararTelaAberturaMovimentoOrdens();
            else
            {
                if (this.ValidarAcaoAbrirReabrir())
                    this._view.PrepararTelaAberturaReaberturaMovimentoOrdens();
                else
                {
                    if (this.ValidarAcaoReabrir())
                        this._view.PrepararTelaReaberturaMovimentoOrdens();
                    else
                    {
                        if (this.ValidarAcaoFechar())
                            this._view.PrepararTelaFechamentoMovimentoOrdens();
                    }
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private DateTime CalcularDataAberturaMovimento()
        {
            DateTime dataAberturaMovimento = new DateTime();
            try
            {
                this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);
                dataAberturaMovimento = ((Model.DataMovimento)this._communicationControleMovimentoOrdens.CalcularDataAberturaMovimento()).Valor;                
            }
            catch (Exception ex)
            {
                HandleException(ex);                
            }
            return dataAberturaMovimento;
        }

        /// <summary>
        /// 
        /// </summary>
        private void CarregarInformacoes()
        {
            this.DataAtualSistema = this.ObterDataAtual();           
            this.InformacoesMovimentoOrdens = this.ObterInformacoesMovimentoOrdens();
            this.DataMovimento = this.InformacoesMovimentoOrdens.DataMovimento;


            _faturamentoInstalado = (new Sinacor.UI.Bovespa.Movimento.Communication.Acesso(this.Session)).VerificarSistemaInstalado("BOL");

            if (_faturamentoInstalado)
                this.InformacoesMovimentoBolsa = this.ObterInformacoesMovimentoBolsa();

            this.DataMovimentoD1 = this.CalcularDataAberturaMovimento();

            _view.ApresentarDataAtual();
            _view.ApresentarDataMovimento();
            _view.ApresentarDataMovimentoD1();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool ValidarAcaoAbrir()
        {
            if (_faturamentoInstalado)
            {
                if ((this.InformacoesMovimentoOrdens.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Fechamento)
                    && (InformacoesMovimentoOrdens.DataMovimento == this.InformacoesMovimentoBolsa.DataMovimento
                    && InformacoesMovimentoBolsa.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Fechamento))
                    return true;
                else
                    return false;
            }
            else
                return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool ValidarAcaoAbrirReabrir()
        {
            if (_faturamentoInstalado)
            {
                if ((InformacoesMovimentoOrdens.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Fechamento) 
                    && ((InformacoesMovimentoOrdens.DataMovimento == InformacoesMovimentoBolsa.DataMovimento 
                    && InformacoesMovimentoBolsa.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Abertura) 
                    || (InformacoesMovimentoOrdens.DataMovimento > InformacoesMovimentoBolsa.DataMovimento)))
                    return true;
                else
                    return false;
            }
            else
            {
                if ((InformacoesMovimentoOrdens.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Fechamento))
                    return true;
                else
                    return false;
            }


        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool ValidarAcaoReabrir()
        {
            return (this.InformacoesMovimentoOrdens.EstadoMovimento == Model.Enum.TipoMovimento.ProcessoFechamento);           
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private bool ValidarAcaoFechar()
        {
            if(_faturamentoInstalado)
            {
                if ((InformacoesMovimentoOrdens.DataMovimento <= DataAtualSistema.Valor 
                    && InformacoesMovimentoOrdens.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Abertura) 
                    && (InformacoesMovimentoOrdens.DataMovimento >= InformacoesMovimentoBolsa.DataMovimento 
                    && (InformacoesMovimentoBolsa.EstadoMovimento ==Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Abertura 
                    || InformacoesMovimentoBolsa.EstadoMovimento ==Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Fechamento)))
                    return true;
                else
                    return false;
            }
            else
            {
                if ((InformacoesMovimentoOrdens.DataMovimento <= DataAtualSistema.Valor) 
                    && (InformacoesMovimentoOrdens.EstadoMovimento == Sinacor.UI.Bovespa.Movimento.Model.Enum.TipoMovimento.Abertura))
                    return true;
                else
                    return false;
            }
   

        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private Model.DataAtual ObterDataAtual()
        {
            Model.DataAtual dataAtual = new Model.DataAtual();
            try
            {
                this._communicationCalendario = new Communication.Calendario(this.Session);
                dataAtual = this._communicationCalendario.ObterDataAtual();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return dataAtual;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>        
        private Model.InformacoesMovimento ObterInformacoesMovimentoBolsa()
        {
            Model.InformacoesMovimento informacoesMovimento = new Model.InformacoesMovimento();
            try
            {
                this._communicationControleMovimentoBolsa = new Communication.ControleMovimentoBolsa(this.Session);
                informacoesMovimento = this._communicationControleMovimentoBolsa.ObterInformacoesMovimento(new Model.DataMovimento());
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return informacoesMovimento;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>        
        private Model.InformacoesMovimento ObterInformacoesMovimentoOrdens()
        {
            Model.InformacoesMovimento informacoesMovimento = new Model.InformacoesMovimento();
            try
            {
                this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens(this.Session);
                informacoesMovimento = this._communicationControleMovimentoOrdens.ObterInformacoesMovimento(new Model.DataMovimento());
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return informacoesMovimento;
        }

        #endregion        

    }
}
